#ifndef LW_STACK_H
#define LW_STACK_H

#include <stack>

#include "abstract/EdgeAccessList.h"

template<typename T>
class Stack : public EdgeAccessList<T> {
protected:
    std::stack<T> wrappedList;
	static const std::string emptyAccessMessage;

public:

	Stack() {
		
	}

    virtual ~Stack() {
    }

    /**
     * Retrieves and removes the top element from this stack.
     */
    virtual inline Stack& operator>>(T& e) {
        Pop(e);
        return *this;
    }

    /**
     * Returns the top element of this stack.
     */
    virtual inline T& Top() {
		if(!Empty()) {
			return wrappedList.top();
		}

		throw std::runtime_error(emptyAccessMessage);
    }

    /**
     * Removes the top element from this stack.
     */
    virtual inline void Pop() {
		wrappedList.pop();
    }

    /**
     * Retrieves and removes the top element from this stack.
     */
    virtual inline void Pop(T& e) {
		if(!Empty()) {
			e = wrappedList.top();
			wrappedList.pop();
			return;
		}

		throw std::runtime_error(emptyAccessMessage);
    }

    /**
     * Adds the specified element to the top of this stack.
     */
    virtual inline void Push(const T& e) {
        wrappedList.push(e);
    }

    /**
     * Returns the number of elements in this stack.
     */
    virtual inline int Size() const {
        return wrappedList.size();
    }

    /**
     * Returns true if this stack has no elements.
     */
    virtual inline bool Empty() const {
        return wrappedList.empty();
    }

    /**
     * Clears the stack by removing each element in a loop.
     */
    virtual void Clear() {
		if(!Empty()) {
			wrappedList.pop();
		}
    }
};

template<typename T>
const std::string Stack<T>::emptyAccessMessage = "Stack (std::stack) is empty";

#endif //LW_STACK_H
